home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / BPNN132U.ARJ / NNTRAIN.C < prev    next >
C/C++ Source or Header  |  1992-04-27  |  9KB  |  419 lines

  1. /*
  2. *-----------------------------------------------------------------------------
  3. *    file:    nntrain.c
  4. *    desc:    train a fully connected neural net by backpropagation
  5. *    by:    patrick ko
  6. *    date:    2 aug 91
  7. *    revi:    v1.2b - 15 jan 92, adaptive coefficients
  8. *        v1.3u - 18 jan 92, revised data structures
  9. *        v1.31u - 20 jan 92, periodic dump, weights retrieval
  10. *-----------------------------------------------------------------------------
  11. */
  12. #include <stdio.h>
  13. #include <math.h>
  14. #include <values.h>
  15. #include <time.h>
  16.  
  17. #include "nntype.h"
  18. #include "nnmath.h"
  19. #include "nntrain.h"
  20. #include "nndump.h"
  21.  
  22. #define    global
  23. #define    LAMBDA0    0.1
  24.  
  25. static REAL    ETA = ETA_DEFAULT;
  26. static REAL    MOMENTUM = ALPHA_DEFAULT;
  27. static REAL    LAMBDA = LAMBDA_DEFAULT;
  28. static INTEGER    REPINTERVAL = 0;
  29. global REAL    TOLER = TOLER_DEFAULT;
  30.  
  31. /*
  32. *=============================================================================
  33. *    funct:    nnbp_train
  34. *    dscpt:    train a neural net using backpropagation
  35. *    given:    net = the neural net
  36. *        inpvect = 1 input vector ( 1 train pattern )
  37. *        tarvect = 1 target vector ( 1 target pattern )
  38. *        np = number of patterns
  39. *        err = error
  40. *        eta, momentum
  41. *        report = dump info interval (no.of train cycles), 0=not dump
  42. *        tdump = no of seconds for periodic dump, 0=not dump
  43. *        dfilename = period dump file name
  44. *    retrn:    measure of error
  45. *=============================================================================
  46. */
  47. REAL nnbp_train( net, inpvect, tarvect, np, err, eta, momentum, report, tdump, dfilename )
  48. NET    *net;
  49. VECTOR    **inpvect;
  50. VECTOR    **tarvect;
  51. REAL    err, eta, momentum;
  52. INTEGER    np, report;
  53. long int tdump;
  54. char    *dfilename;
  55. {
  56.     REAL    Error;
  57.     INTEGER    cnt;
  58.     time_t    lasttime, thistime;
  59.     FILE    *fdump;
  60.  
  61.  
  62.     cnt = 0;
  63.     REPINTERVAL = report;
  64.     ETA = eta;
  65.     MOMENTUM = momentum;
  66.     Error = MAXFLOAT;
  67.     if (tdump)
  68.         time(&lasttime);
  69.  
  70.     while (Error > err)
  71.         {
  72.         cnt++;
  73.         Error = nnbp_train1( net, inpvect, tarvect, np, Error );
  74.  
  75.         if (report)
  76.             nnbp_report(cnt, Error);
  77.         if (tdump)
  78.             {
  79.             if (((thistime = time(&thistime)) - lasttime) >= tdump)
  80.                 {
  81.                 fdump = fopen( dfilename, "w" );
  82.                 nn_dump( fdump, net );
  83.                 fclose(fdump);
  84.                 lasttime = thistime;
  85.                 }
  86.             }
  87.         }
  88.     return (Error);
  89. }
  90.  
  91. /*
  92. *=============================================================================
  93. *    funct:    nnbp_report
  94. *    dscpt:    print report lines to terminal
  95. *    given:    cnt = number of train cycles
  96. *        error = overall energy
  97. *    retrn:    nothing
  98. *=============================================================================
  99. */
  100. void nnbp_report( cnt, error )
  101. INTEGER    cnt;
  102. REAL    error;
  103. {
  104.     if (!(cnt%REPINTERVAL))
  105.         {
  106.         printf("nntrain: cycle %d, mean square error per unit =%f\n", cnt, error );
  107.         }
  108. }
  109.  
  110. /*
  111. *=============================================================================
  112. *    funct:    nnbp_train1
  113. *    dscpt:    train a neural net 1 cycle using backpropagation
  114. *    given:    net = the neural net
  115. *        inpvect = 1 set of input vectors
  116. *        tarvect = 1 set of target vectors
  117. *        np = number of patterns
  118. *        LastError = energy at last cycle
  119. *    retrn:    measure of error after this train cycle
  120. *=============================================================================
  121. */
  122. REAL nnbp_train1( net, inpvect, tarvect, np, LastError )
  123. NET    *net;
  124. VECTOR    **inpvect;
  125. VECTOR     **tarvect;
  126. INTEGER    np;
  127. REAL    LastError;
  128. {
  129.     REAL    Error;
  130.     INTEGER    i;
  131.     INTEGER    fire=0;
  132.  
  133.     Error = 0.0;
  134.     nnbp_init( net );
  135.     for (i=0; i<np; i++)
  136.         {
  137.         nnbp_forward( net, *(inpvect + i));
  138.         Error += nnbp_backward( net, *(inpvect + i), *(tarvect + i));
  139.         }
  140.     Error = Error / np / DimNetOut(net);
  141.     /*
  142.     * coefficients adaptation and dWeight calculations
  143.     */
  144.     if (Error <= LastError + TOLER )
  145.         {
  146.  
  147.         /* weights will be updated, go ahead */
  148.  
  149.         fire = 1;
  150.         nnbp_coeffadapt( net );
  151.         nnbp_dweightcalc( net, np, fire );
  152.         return (Error);
  153.         }
  154.     else
  155.         {
  156.  
  157.         /* weights will not be updated, backtrack */
  158.  
  159.         fire = 0;
  160.         ETA *= BACKTRACK_STEP;        /* half the ETA */
  161.         ETA = ground(ETA,ETA_FLOOR);
  162.         MOMENTUM = ETA * LAMBDA;
  163.         nnbp_dweightcalc( net, np, fire );
  164.         return (LastError);
  165.         }
  166. }
  167.  
  168. /*
  169. *=============================================================================
  170. *    funct:    nnbp_forward (pass)
  171. *    dscpt:    forward pass calculation
  172. *    given:    net = the neural net
  173. *        inpvect = 1 input vector ( 1 train pattern )
  174. *    retrn:    nothing
  175. *    cmmnt:    net's output Out(J) calculated at every unit
  176. *=============================================================================
  177. */
  178. void nnbp_forward( net, inpvect )
  179. NET    *net;
  180. VECTOR    *inpvect;
  181. {
  182.     LAYER    *I, *input;
  183.     UNIT    *J;
  184.     INTEGER    i, j, k;
  185.     REAL    sum, out;
  186.  
  187.     /* phase 1 - forward compute output value Out's */
  188.  
  189.     input = NULL;
  190.  
  191.     /* For each layer I in the network */
  192.  
  193.     for (i=0; i<DimNet(net); i++)
  194.         {
  195.         I = Layer(net,i);
  196.  
  197.         /* For each unit J in the layer */
  198.  
  199.         for (j=0; j<DimLayer(I); j++)
  200.             {
  201.             J = Unit(I,j);
  202.             Net(J) = Bias(J) + dBias1(J); /* add bias */
  203.             for (k=0; k<DimvWeight(J); k++)
  204.                 {
  205.                 if (i==0)
  206.                     out = Vi(inpvect,k);
  207.                 else
  208.                     out = Out(Unit(input,k));
  209.  
  210.                 Net(J) += (Weight(J,k) + dWeight1(J,k)) * out;
  211.                 }
  212.             Out(J) = sigmoid(Net(J));
  213.             }
  214.         input = I;
  215.         }
  216. }
  217.  
  218.  
  219. void nnbp_init( net )
  220. NET    *net;
  221. {
  222.     LAYER    *I;
  223.     UNIT    *J;
  224.     INTEGER    i, j, k;
  225.  
  226.     i = DimNet(net);
  227.  
  228.     while (i--)
  229.         {
  230.         I = Layer(net,i);
  231.         for (j=0; j<DimLayer(I); j++)
  232.             {
  233.             J = Unit(I,j);
  234.             nDlt(J) = 0.0;
  235.             for (k=0; k<DimvWeight(J); k++)
  236.                 {
  237.                 DO(J,k) = 0.0;
  238.                 }
  239.             }
  240.         }
  241. }
  242.  
  243. /*
  244. *=============================================================================
  245. *    funct:    nnbp_backward
  246. *    dscpt:    backward pass calculation
  247. *    given:    net = the neural net
  248. *        inpvect = 1 input vector ( 1 train pattern )
  249. *        tarvect = 1 target vector
  250. *    retrn:    Ep * 2
  251. *    cmmnt:    net's weight and bias adjusted at every layer
  252. *=============================================================================
  253. */
  254. REAL nnbp_backward( net, inpvect, tarvect )
  255. NET    *net;
  256. VECTOR    *inpvect;
  257. VECTOR    *tarvect;
  258. {
  259.     LAYER    *I, *F, *B;
  260.     UNIT    *J, *JF;
  261.     INTEGER    i, j, k;
  262.     REAL    sum, out;
  263.     REAL    Ep, diff;
  264.  
  265.     Ep = 0.0;
  266.  
  267.     /*
  268.     *    phase 2 - target comparison and back propagation
  269.     */
  270.     i = DimNet(net) - 1;
  271.     F = I = Layer(net,i);
  272.     B = Layer(net,i - 1);
  273.  
  274.     /*
  275.     *    Delta rule 1 - OUTPUT LAYER
  276.     *    dpj = (tpj - opj) * f'(netpj)
  277.     */
  278.     for (j=0; j<DimLayer(I); j++)
  279.         {
  280.         J = Unit(I,j);
  281.         diff = Vi(tarvect,j) - Out(J);
  282.         Dlt(J) = diff * Out(J) * (1.0 - Out(J));
  283.  
  284.         nDlt(J) += Dlt(J);    /* accumulate Dpj's */
  285.  
  286.         for (k=0; k<DimvWeight(J); k++)
  287.             {
  288.             if (i==0)
  289.                 out = Vi(inpvect,k);
  290.             else
  291.                 out = Out(Unit(B,k));
  292.             DO(J,k) += Dlt(J) * out;
  293.             }
  294.  
  295.         Ep += diff * diff;
  296.         }
  297.  
  298.     --i;
  299.     while (i >= 0)
  300.         {
  301.         I = Layer(net,i);        /* current layer */
  302.         B = Layer(net,i - 1);
  303.         /*
  304.         *    delta rule 2 - HIDDEN LAYER:
  305.         *    dpj = f'(netpj) * SUMMATEk( Dpk * Wkj )
  306.         */
  307.         for (j=0; j<DimLayer(I); j++)
  308.             {
  309.             J = Unit(I,j);
  310.             sum = 0.0;
  311.             for (k=0; k<DimLayer(F); k++)
  312.                 {
  313.                 JF = Unit(F,k);
  314.                 sum += Dlt(JF) * (Weight(JF,j)+dWeight1(JF,j));
  315.                 }
  316.             Dlt(J) = Out(J) * (1.0 - Out(J)) * sum;
  317.             nDlt(J) += Dlt(J);
  318.  
  319.             for (k=0; k<DimvWeight(J); k++)
  320.                 {
  321.                 if (i==0)
  322.                     out = Vi(inpvect,k);
  323.                 else
  324.                     out = Out(Unit(B,k));
  325.                 DO(J,k) += Dlt(J) * out;
  326.                 }
  327.             }
  328.         F = I;
  329.         i--;
  330.         }
  331.  
  332.     return (Ep);
  333. }
  334.  
  335. void nnbp_coeffadapt( net )
  336. NET    *net;
  337. {
  338.     LAYER    *I, *B;
  339.     UNIT    *J;
  340.     INTEGER    n, i, j, k;
  341.     REAL    EW, ME, MW, costh;
  342.  
  343.     EW = ME = MW = 0.0;
  344.     i = DimNet(net);
  345.  
  346.     while (i--)
  347.         {
  348.         I = Layer(net,i);
  349.         for (j=0; j<DimLayer(I); j++)
  350.             {
  351.             J = Unit(I,j);
  352.             for (k=0; k<DimvWeight(J); k++)
  353.                 {
  354.                 ME += DO(J,k) * DO(J,k);
  355.                 MW += dWeight1(J,k) * dWeight1(J,k);
  356.                 EW += DO(J,k) * dWeight1(J,k);
  357.                 }
  358.             }
  359.         }
  360.  
  361.     ME = sqrt(ME);        /* modulus of cost funct vector E */
  362.     MW = sqrt(MW);        /* modulus of delta weight vector dWn-1*/
  363.  
  364.     ME = ground(ME,ME_FLOOR);        /* constraints */
  365.     MW = ground(MW,MW_FLOOR);        /* constraints */
  366.  
  367.     costh = EW / (ME * MW);
  368.  
  369.     /* coefficients adaptation !!! */
  370.  
  371.     ETA = ETA * (1.0 + 0.5 * costh);
  372.     ETA = ground(ETA,ETA_FLOOR);
  373.     LAMBDA = LAMBDA0 * ME / MW;
  374.     MOMENTUM = ETA * LAMBDA;
  375. }
  376.  
  377. void nnbp_dweightcalc( net, np, fire )
  378. NET    *net;
  379. INTEGER    np;
  380. INTEGER    fire;
  381. {
  382.     LAYER    *I;
  383.     UNIT    *J;
  384.     INTEGER    n, i, j, k;
  385.  
  386.     i = DimNet(net);
  387.  
  388.     /* calculate dWeights for every unit */
  389.  
  390.     while (i--)
  391.         {
  392.         I = Layer(net,i);
  393.         for (j=0; j<DimLayer(I); j++)
  394.             {
  395.             J = Unit(I,j);
  396.             nDlt(J) /= np;
  397.             for (k=0; k<DimvWeight(J); k++)
  398.                 {
  399.                 DO(J,k) /= np;
  400.                 if (fire)
  401.                     {
  402.                     /* commit weight change */
  403.                     Weight(J,k) += dWeight1(J,k);
  404.  
  405.                     /* dW n-2 = dW n-1 */
  406.                     dWeight2(J,k) = dWeight1(J,k);
  407.                     }
  408.                 dWeight1(J,k) = ETA * DO(J,k) + MOMENTUM * dWeight2(J,k);
  409.                 }
  410.             if (fire)
  411.                 {
  412.                 Bias(J) += dBias1(J);
  413.                 dBias2(J) = dBias1(J);
  414.                 }
  415.             dBias1(J) = ETA * nDlt(J) + MOMENTUM * dBias2(J);
  416.             }
  417.         }
  418. }
  419.